package org.saratogaschools.edd.firefighter.client.view;

import java.util.LinkedList;
import java.util.List;

import org.saratogaschools.edd.firefighter.client.util.LatLng;
import org.saratogaschools.edd.firefighter.client.util.LatLngBounds;
import org.saratogaschools.edd.firefighter.client.util.Map;
import org.saratogaschools.edd.firefighter.client.util.Marker;
import org.saratogaschools.edd.firefighter.shared.model.Fire;

import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TabLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;

public class FireListView extends Composite implements
		SelectionChangeEvent.Handler, SelectionHandler<Integer> {

	public interface Presenter {

		void addFire();

		void refresh();

		void selectFire(Fire f);

	}

	private Presenter presenter;

	@UiField
	DivElement mapContainer;
	@UiField
	TabLayoutPanel tabLayoutPanel;
	@UiField(provided = true)
	CellTable<Fire> fireTable;
	
	private List<Marker> markers;

	@UiField
	Button addButton;

	private SingleSelectionModel<Fire> selectionModel;

	Map map;

	private List<Fire> fires;

	private static FireListViewUiBinder uiBinder = GWT
			.create(FireListViewUiBinder.class);

	interface FireListViewUiBinder extends UiBinder<Widget, FireListView> {
	}

	public FireListView() {
		this.fireTable = new CellTable<Fire>();
		this.markers = new LinkedList<Marker>();
		fireTable.addColumn(new CoordinatesColumn(new TextCell()));
		fireTable.addColumn(new AddressColumn(new TextCell()));
		fireTable
				.setEmptyTableWidget(new Label("No fires for this Department"));
		this.selectionModel = new SingleSelectionModel<Fire>();
		fireTable.setSelectionModel(selectionModel);
		selectionModel.addSelectionChangeHandler(this);
		initWidget(uiBinder.createAndBindUi(this));
		this.map = Map.create(mapContainer);
		this.tabLayoutPanel.addSelectionHandler(this);
	}

	public void setPresenter(Presenter presenter) {
		this.presenter = presenter;
	}

	private native void triggerMapResize(Map map) /*-{
		$wnd.google.maps.event.trigger(map, 'resize');
	}-*/;

	@Override
	public void onSelection(SelectionEvent<Integer> event) {
		if (event.getSelectedItem() == 1) {
			Scheduler.get().scheduleDeferred(new ScheduledCommand() {
				@Override
				public void execute() {
					triggerMapResize(map);
					presenter.refresh();
				}
			});
		}
	}

	private class CoordinatesColumn extends Column<Fire, String> {

		public CoordinatesColumn(Cell<String> cell) {
			super(cell);
		}

		@Override
		public String getValue(Fire object) {
			if (object == null) {
				return null;
			} else {
				return "" + object.getLatitude() + ", " + object.getLongitude();
			}
		}

	}

	public void setAddButtonEnabled(boolean enabled) {
		addButton.setEnabled(enabled);
	}

	@UiHandler("addButton")
	void onAddButtonClicked(ClickEvent evt) {
		addButton.setEnabled(false);
		presenter.addFire();
	}

	@UiHandler("refreshButton")
	void onRefreshButtonClicked(ClickEvent evt) {
		presenter.refresh();
	}

	private class AddressColumn extends Column<Fire, String> {

		public AddressColumn(Cell<String> cell) {
			super(cell);
		}

		@Override
		public String getValue(Fire object) {
			if (object == null) {
				return null;
			} else {
				return object.getAddress();
			}
		}

	}

	public void setFires(List<Fire> fires) {
		this.fires = fires;
		fireTable.setRowCount(this.fires.size(), true);
		fireTable.setRowData(this.fires);
		
		// Apply to map
		// First, clear out the old markers
		for (Marker marker : markers) {
			marker.setMap(null);
		}
		markers.clear();
		
		
		// Then, build new ones
		for (Fire f : fires) {
			LatLng latLng = LatLng.create(f.getLatitude(), f.getLongitude());
			Marker marker = Marker.create();
			marker.setPosition(latLng);
			marker.setMap(map);
			markers.add(marker);
			if (f == fires.get(0)) {
				map.setCenter(latLng);
			}
			else {
				LatLngBounds bounds = map.getBounds();
				LatLngBounds extended = bounds.extend(latLng);
				map.panToBounds(extended);
			}
		}
	}
	

	@Override
	public void onSelectionChange(SelectionChangeEvent event) {
		Fire f = selectionModel.getSelectedObject();
		presenter.selectFire(f);
	}

}
